package com.example.zhongshuishi;

import com.example.zhongshuishi.entity.CustomerUserDetails;
import com.example.zhongshuishi.entity.PersonnelDto;
import com.example.zhongshuishi.entity.StudentDto;
import com.example.zhongshuishi.service.PersonnelService;
import com.example.zhongshuishi.service.StudentService;
import com.example.zhongshuishi.utils.JwtTokenUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.PrintWriter;

@Component
public class LogginAuthIntercepter implements HandlerInterceptor {
    Logger LOGGER = LoggerFactory.getLogger(LogginAuthIntercepter.class);
    @Autowired
    private StudentService studentService;
    @Autowired
    private PersonnelService personnelService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Autowired
    private CustomerUserDetails customerUserDetails;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try{
            // 从客户端请求中获取 JWT
            String authHeader = request.getHeader(tokenHeader);
            // 该 JWT 是我们规定的格式，以 tokenHead 开头
            if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
                // The part after "Bearer "
                String authToken = authHeader.substring(this.tokenHead.length());
                // 从 JWT 中获取用户名
                String phoneJwt = jwtTokenUtil.getPhoneFromToken(authToken);
                String roleFromToken = jwtTokenUtil.getRoleFromToken(authToken);
                LOGGER.info("LogginAuthIntercepter preHandle checking phoneJwt:{} roleFromToken:{}", phoneJwt,roleFromToken);

                // SecurityContextHolder 是 SpringSecurity 的一个工具类
                // 保存应用程序中当前使用人的安全上下文
                if (phoneJwt != null) {
                    // 根据用户名获取登录用户信息
                    if("teacher".equals(roleFromToken)) {
                        PersonnelDto personnelDto = personnelService.selectByPhone(phoneJwt);
                        if (personnelDto != null) {
                            customerUserDetails.setId(personnelDto.getId().toString());
                            customerUserDetails.setPhone(personnelDto.getUPhone());
                            customerUserDetails.setIdnumber(personnelDto.getUIdnumber());
                            customerUserDetails.setName(personnelDto.getUndertaker());
                            customerUserDetails.setParentId(personnelDto.getParentId());
                            customerUserDetails.setParentLevel(personnelDto.getPersonLevel());
                            customerUserDetails.setRoleFromToken("teacher");
                        }
                    }
                    if("student".equals(roleFromToken)) {
                        StudentDto studentByPhone = studentService.getStudentByPhone(phoneJwt);
                        if(studentByPhone != null) {
                            customerUserDetails.setId(studentByPhone.getId());
                            customerUserDetails.setPhone(studentByPhone.getStuPhone());
                            customerUserDetails.setWeixin(studentByPhone.getWeixin());
                            customerUserDetails.setIdnumber(studentByPhone.getStuIdnumber());
                            customerUserDetails.setName(studentByPhone.getStuName());
                            customerUserDetails.setTeacherName(studentByPhone.getTeacher());
                            customerUserDetails.setTeacherId(studentByPhone.getTeacherId());
                            customerUserDetails.setRoleFromToken("student");
                        }
                    }
                    // 验证 token 是否过期
                    if (jwtTokenUtil.validateToken(authToken, customerUserDetails.getPhone())) {
                        LOGGER.info("LogginAuthIntercepter preHandle authToken :{},uPhone:{}", authToken,customerUserDetails.getPhone());

                        if(SecurityContextHolder.getContext().getAuthentication() == null){
                            // 将登录用户保存到安全上下文中
                            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(customerUserDetails,
                                    null, customerUserDetails.getAuthorities());
                            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                            SecurityContextHolder.getContext().setAuthentication(authentication);
                        }

                        return true;
                    }
                }
            }
            response.setStatus(HttpStatus.FORBIDDEN.value());
            PrintWriter writer = response.getWriter();
            ObjectMapper objectMapper = new ObjectMapper();
            writer.write(objectMapper.writeValueAsString(ResponseEntity.status(403).body("已过期请重新登录")));
            writer.flush();
            return false;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }
}
